<?php
namespace Conf;

use Core\AbstractInterface\AbstractEvent;
use Core\AutoLoader;
use Core\Component\Di;
use Core\Component\SysConst;
use Core\Component\Logger;
use Core\Http\Request;
use Core\Http\Response;
use Core\Swoole\AsyncTaskManager;
use Core\Swoole\Server;
use App\Controller\WebSocket;
use App\Model\Users;
use App\Vendor\Redis;
use App\Vendor\StringHelper;

class Event extends AbstractEvent
{
    function frameInitialize()
    {
        date_default_timezone_set('Asia/Shanghai');
        $loader = AutoLoader::getInstance();
        $loader->requireFile("App/Vendor/MysqliDb.php");
        $conf = Config::getInstance()->getConf('MYSQL');
        Di::getInstance()->set(SysConst::MYSQL,\MysqliDb::class,$conf['HOST'],$conf['USER'],$conf['PASSWORD'],$conf['DB_NAME']);
//        Di::getInstance()->set(SysConst::REDIS, (new \App\Vendor\Redis()));
//        $redis = Di::getInstance()->get("REDIS");
    }

    function frameInitialized()
    {
        // TODO: Implement frameInitialized() method.
    }


    function beforeWorkerStart(\swoole_server $server)
    {
        $server->on(
            "handshake",
            function ($request,$response){
                $loginId = $request->get['userId'];
                Logger::getInstance()->console("your request take ".$loginId."");
                if (!$loginId) {
                    $response->status(10001);
                    $response->end();
                    return false;
                }
                $userInfo=(new Users())->getUserInfoById($loginId);
                Logger::getInstance()->console("your request take ".json_encode($userInfo)."");
                if (!$userInfo) {
                    $response->status(10001);
                    $response->end();
                    return false;
                }
                //自定定握手规则，没有设置则用系统内置的（只支持version:13的）
                if (!isset($request->header['sec-websocket-key'])){
                    //'Bad protocol implementation: it is not RFC6455.'
                    $response->status(10002);
                    $response->end();
                    return false;
                }
                if (0 === preg_match('#^[+/0-9A-Za-z]{21}[AQgw]==$#', $request->header['sec-websocket-key'])
                    || 16 !== strlen(base64_decode($request->header['sec-websocket-key']))
                ){
                    //Header Sec-WebSocket-Key is illegal;
                    $response->end();
                    return false;
                }

                $key = base64_encode(sha1($request->header['sec-websocket-key'].'258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true));
                $headers = array(
                    'Upgrade'               => 'websocket',
                    'Connection'            => 'Upgrade',
                    'Sec-WebSocket-Accept'  => $key,
                    'Sec-WebSocket-Version' => '13',
                    'KeepAlive'             => 'off',
                );
                foreach ($headers as $key => $val){
                    $response->header($key, $val);
                }
                $userInfo['FD']=$request->fd;
                $userInfo['onLine']=1;
                Logger::getInstance()->console("your request take ".$request->fd."");
                $conf = Config::getInstance()->getConf('REDISMAP');
                $redis = new Redis();
                $redis->hSet($conf['SWOOLE_USER_LIST'],$userInfo['userId'],json_encode($userInfo));
                AsyncTaskManager::getInstance()->add(
                    function () use($userInfo,$conf){
                        $redis = new Redis();
                        $list = $redis->hGet($conf['SWOOLE_USER_PERSON_LIST'],$userInfo['userId']);
                        if(!empty($list)){
                            $list=json_decode($list,TRUE);
                            foreach ($list as $each){
                                $info = $redis->hGet($conf['SWOOLE_USER_LIST'],$each);
                                if(!empty($info)){
                                    $info = json_decode($info,TRUE);
                                    if($info['onLine'] && $info['userId']!=$userInfo['userId']){
                                        $retrun['type']='login';
                                        $retrun['user']=$userInfo;
                                        $retrun['content']='上线了';
                                        $retrun['time']=StringHelper::getDateTime(1);
                                        $retrun['chatFlag']='';
                                        $retrun['chat']=(object)[];
                                        Server::getInstance()->getServer()->push($info['FD'],json_encode($retrun));
                                    }
                                }
                            }
                        }
                    }
                );
                //注意 一定要有101状态码，协议规定
                $response->status(101);
                $response->end();
            }
        );

        $server->on(
            "message",
            function (\swoole_websocket_server $server, \swoole_websocket_frame $frame){
                $json = json_decode($frame->data,TRUE);
                if($json['chatType']==1){
                    (new WebSocket)->talkOne($json);
                }elseif($json['chatType']==2) {
                    (new WebSocket)->talkAll($json);
                }
            }
        );

        $server->on("close",function ($ser,$fd){
            $redis = new Redis();
            $conf = Config::getInstance()->getConf('REDISMAP');
            $list = $redis->hGetAll($conf['SWOOLE_USER_LIST']);
            $userInfo = '';
            if(!empty($list)){
                foreach ($list as $userId => $info){
                    if(!empty($info)){
                        $info = json_decode($info,TRUE);
                        if($info['FD'] == $fd){
                            $info['onLine']=0;
                            $redis->hSet($conf['SWOOLE_USER_LIST'],$userId,json_encode($info));
                            $userInfo = $info;
                        }
                    }
                }
            }
            if(!empty($userInfo)){
                AsyncTaskManager::getInstance()->add(
                    function () use($userInfo,$conf){
                        $redis = new Redis();
                        $list = $redis->hGet($conf['SWOOLE_USER_PERSON_LIST'],$userInfo['userId']);
                        if(!empty($list)){
                            $list=json_decode($list,TRUE);
                            foreach ($list as $each){
                                $info = $redis->hGet($conf['SWOOLE_USER_LIST'],$each);
                                if(!empty($info)){
                                    $info = json_decode($info,TRUE);
                                    if($info['onLine'] && $info['userId']!=$userInfo['userId']){
                                        $retrun['type']='logout';
                                        $retrun['user']=$userInfo;
                                        $retrun['content']='下线了';
                                        $retrun['time']=StringHelper::getDateTime(1);
                                        $retrun['chatFlag']='';
                                        $retrun['chat']=(object)[];
                                        Server::getInstance()->getServer()->push($info['FD'],json_encode($retrun));
                                    }
                                }
                            }
                        }
                    }
                );
            }
        });
    }

    function onStart(\swoole_server $server)
    {
        // TODO: Implement onStart() method.
    }

    function onShutdown(\swoole_server $server)
    {
        // TODO: Implement onShutdown() method.
    }

    function onWorkerStart(\swoole_server $server, $workerId)
    {
        // TODO: Implement onWorkerStart() method.
    }

    function onWorkerStop(\swoole_server $server, $workerId)
    {
        // TODO: Implement onWorkerStop() method.
    }

    function onRequest(Request $request, Response $response)
    {
        $request->withAttribute("startTime",microtime(true));
    }

    function onDispatcher(Request $request, Response $response, $targetControllerClass, $targetAction)
    {
        // TODO: Implement onDispatcher() method.
    }

    function onResponse(Request $request,Response $response)
    {
        $end = microtime(true);
        $ret = $end - $request->getAttribute("startTime");
        Logger::getInstance()->console("your request take {$ret}");
    }

    function onTask(\swoole_server $server, $taskId, $workerId, $taskObj)
    {
        // TODO: Implement onTask() method.
    }

    function onFinish(\swoole_server $server, $taskId, $taskObj)
    {
        // TODO: Implement onFinish() method.
    }

    function onWorkerError(\swoole_server $server, $worker_id, $worker_pid, $exit_code)
    {

        // TODO: Implement onWorkerError() method.
    }
}
